// Copyright (C) 1953-2023 NUDT
// Verilog module name - descriptor_dispatch   
// Version: V4.3.0.20230309
// Created:
//         by - fenglin 
////////////////////////////////////////////////////////////////////////////
// Description:
//         Descriptor Send
///////////////////////////////////////////////////////////////////////////

`timescale 1ns/1ps
 
module descriptor_dispatch 
(
        i_clk,
        i_rst_n,
        
        iv_desp          ,       
        iv_st_inject_dbufid,
        i_desp_wr       ,
        
        o_st_desp_wr,
        ov_st_desp,
        ov_st_inject_dbufid,
        
        o_rcbe_desp_wr,
        ov_rcbe_desp,
        i_rcbe_desp_ack
    );

// I/O
// clk & rst
input                   i_clk;
input                   i_rst_n;
//input
(*MARK_DEBUG="true"*)input       [11:0]      iv_desp;
(*MARK_DEBUG="true"*)input       [4:0]       iv_st_inject_dbufid;
(*MARK_DEBUG="true"*)input                   i_desp_wr;

output  reg             o_st_desp_wr;
output  reg [11:0]      ov_st_desp;
output  reg [4:0]       ov_st_inject_dbufid;

(*MARK_DEBUG="true"*)output  reg             o_rcbe_desp_wr;
(*MARK_DEBUG="true"*)output  reg [11:0]      ov_rcbe_desp;
(*MARK_DEBUG="true"*)input                   i_rcbe_desp_ack;
//temp ov_descriptor and ov_pkt for discarding pkt while the fifo_used_findows is over the threshold 
//internal wire&reg
(*MARK_DEBUG="true"*)reg         [1:0]  descriptor_send_state;
localparam  idle_s                     = 2'b00,
            delay_st_transmit_s        = 2'b01,
            delay_rcbe_transmit_s      = 2'b10,
            wait_rcbe_des_ack_s        = 2'b11;
        
always@(posedge i_clk or negedge i_rst_n)
    if(!i_rst_n) begin
        o_st_desp_wr          <= 1'b0;
        ov_st_desp            <= 12'b0;
        ov_st_inject_dbufid   <= 5'b0;
        
        o_rcbe_desp_wr        <= 1'b0;
        ov_rcbe_desp          <= 12'b0;	
        
        descriptor_send_state <= idle_s;
    end
    else begin
        case(descriptor_send_state)
            idle_s:begin
                if(i_desp_wr)begin
                    if(iv_desp[11:9] >= 3'd5)begin
                        ov_st_desp          <= iv_desp;
                        ov_st_inject_dbufid <= iv_st_inject_dbufid;
                        o_st_desp_wr          <= 1'b1;
                        
                        o_rcbe_desp_wr        <= 1'b0;
                        ov_rcbe_desp          <= 12'b0;	 
                        
                        descriptor_send_state <= idle_s;                        
                    end
                    else begin
                        o_st_desp_wr          <= 1'b0;
                        ov_st_desp            <= 12'b0;
                        ov_st_inject_dbufid   <= 5'b0;                        
                    
                        o_rcbe_desp_wr        <= 1'b1;
                        ov_rcbe_desp          <= iv_desp;
                        
                        descriptor_send_state <= wait_rcbe_des_ack_s;
                    end                   												                     
                end
                else begin
                    o_st_desp_wr          <= 1'b0;
                    ov_st_desp            <= 12'b0;
                    ov_st_inject_dbufid   <= 5'b0; 

                    o_rcbe_desp_wr        <= 1'b0;
                    ov_rcbe_desp          <= 12'b0;	                                      
                    descriptor_send_state <= idle_s;
                end
            end           
            wait_rcbe_des_ack_s:begin  
                o_st_desp_wr          <= 1'b0;
                ov_st_desp            <= 12'b0;
                ov_st_inject_dbufid   <= 5'b0;             
                if(i_rcbe_desp_ack == 1'b1) begin
                    o_rcbe_desp_wr        <= 1'b0;
                    ov_rcbe_desp          <= 12'b0;	
                    descriptor_send_state       <= idle_s;
                end
                else begin
                    descriptor_send_state <= wait_rcbe_des_ack_s;
                end
                
            end
            default:begin
                o_st_desp_wr          <= 1'b0;
                ov_st_desp            <= 12'b0;
                ov_st_inject_dbufid   <= 5'b0;
                
                o_rcbe_desp_wr        <= 1'b0;
                ov_rcbe_desp          <= 12'b0;	

                descriptor_send_state <= idle_s;
           end
        endcase
    end
endmodule